package com.pwc.conversionTool.biz;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.google.appengine.api.blobstore.BlobInfo;
import com.googlecode.objectify.Key;
import com.pwc.conversionTool.biz.sendSoap.DataAdaptorProcess;
import com.pwc.conversionTool.biz.sendSoap.SendProcess;
import com.pwc.conversionTool.biz.sendSoap.TaskFlowProcess;
import com.pwc.conversionTool.dao.AccountDao;
import com.pwc.conversionTool.dao.LogDao;
import com.pwc.conversionTool.dao.ProjectDao;
import com.pwc.conversionTool.dao.TaskDao;
import com.pwc.conversionTool.dataAdaptor.DataAdaptor;
import com.pwc.conversionTool.dataAdaptor.DataFilter;
import com.pwc.conversionTool.dataAdaptor.FormulaProcess;
import com.pwc.conversionTool.dataAdaptor.IDataAdaptor;
import com.pwc.conversionTool.entity.Account;
import com.pwc.conversionTool.entity.DataTemplate;
import com.pwc.conversionTool.entity.Formula;
import com.pwc.conversionTool.entity.FormulaRestEntity;
import com.pwc.conversionTool.entity.Log;
import com.pwc.conversionTool.entity.Operation;
import com.pwc.conversionTool.entity.Task;
import com.pwc.conversionTool.entity.TaskFlow;
import com.pwc.conversionTool.entity.TaskFlowLog;
import com.pwc.conversionTool.entity.TaskFlowRunningType;
import com.pwc.conversionTool.entity.TaskLog;

public class TaskBiz {

	private TaskDao taskDao = new TaskDao();

	private ProjectDao projectDao = new ProjectDao();

	private AccountDao accountDao = new AccountDao();
	
	private ProjectBiz projectBiz=new ProjectBiz();
	
	private DataAdaptorBiz dataAdaptorBiz=new DataAdaptorBiz();
	
	private LogDao logDao=new LogDao();

	public TaskFlow createTaskFlow(String taskFlowName, Key<Account> accountKey) {
		TaskFlow taskFlow = new TaskFlow(taskFlowName, TaskFlowRunningType.NEW, accountKey);

		taskDao.saveTaskFlow(taskFlow);

		return taskFlow;
	}

	public void saveTask(Long taskFlowId, Long id, String taskName, Long operationId, String errorPath, String errorValue,
			List<BlobInfo> infos) {

		Task task = null;
		Operation operation = null;
		TaskFlow taskflow = null;

		if (taskFlowId != null)// must not empty
		{
			taskflow = taskDao.getTaskFlowById(taskFlowId);

			if (id != null) {
				task = taskDao.getTaskById(id);// update
			} else {
				task = new Task();
			}

			if (operationId != null) {
				operation = projectDao.getOperationById(operationId);// get
																		// operation
																		// from
			}

			task.setTaskName(taskName);
			task.setTaskFlowKey(taskflow.getKey());
			task.setOperation(operation.getKey());
			task.setErrorPath(errorPath);
			task.setErrorValue(errorValue);

			List<String> keys = new ArrayList<String>();

			for (BlobInfo info : infos) {
				keys.add(info.getBlobKey().getKeyString());
			}

			task.setFiles(keys);

			Key<Task> taskKey = taskDao.saveTask(task);// save to get key

			if (taskflow.getFirstTaskKey() == null && taskflow.getLastTaskKey() == null) {
				taskflow.setFirstTaskKey(taskKey);
				taskflow.setLastTaskKey(taskKey);

			} else {

				Task laskTask = taskDao.getTaskByKey(taskflow.getLastTaskKey());

				laskTask.setNextTaskKey(taskKey);

				taskflow.setLastTaskKey(taskKey);

				taskDao.saveTask(laskTask);

			}

			taskDao.saveTaskFlow(taskflow);

		}

	}

	public TaskFlow getTaskFlowById(Long taskFlowId) {

		if (taskFlowId != null) {
			TaskFlow taskFlow=taskDao.getTaskFlowById(taskFlowId);
			
			taskFlow.setTaskFlowLog(logDao.getTaskFlowLog(taskFlow));	
			
			return  taskFlow;
		} else {
			return null;
		}

	}

	public List<Task> getTasksByTaskFlowId(Long taskFlowId) {

		TaskFlow taskFlow = getTaskFlowById(taskFlowId);

		List<Task> result = new ArrayList<Task>();

		if (taskFlow != null) {

			if (taskFlow.getFirstTaskKey() == null || taskFlow.getLastTaskKey() == null) {
				return null;
			} else {

				Key<Task> targetKey = taskFlow.getFirstTaskKey();

				while (targetKey != null) {
					Task targetTask = taskDao.getTaskByKey(targetKey);
					
					targetTask.setTaskLog(logDao.getTaskLogByTask(targetTask)); 
					
					if (targetTask != null) {
						result.add(targetTask);
						targetKey = targetTask.getNextTaskKey();
					}
				}

				return result;
			}

		} else {
			return null;
		}
	}

	public void deleteTaskById(Long id) {

		Task target = taskDao.getTaskById(id);

		TaskFlow taskFlow = taskDao.getTaskFlowByKey(target.getTaskFlowKey());

		// if this is the first

		if (taskFlow.getFirstTaskKey().equals(target.getKey())) {
			taskFlow.setFirstTaskKey(target.getNextTaskKey());
		}

		Task previous = taskDao.getPreviousTask(target.getKey());

		if (previous != null) {
			previous.setNextTaskKey(target.getNextTaskKey());
			taskDao.saveTask(previous);
		}

		if (taskFlow.getLastTaskKey().equals(target.getKey())) {
			if (previous != null) {
				taskFlow.setLastTaskKey(previous.getKey());
			} else {
				taskFlow.setLastTaskKey(null);
			}

		}

		taskDao.saveTaskFlow(taskFlow);

		// delete it
		taskDao.deleteTaskById(id);

	}

	
	/**
	 * main function for send soap
	 * @param id
	 * @return
	 */
	public boolean startTaskFlow(Long id) {

		TaskFlow taskFlow = taskDao.getTaskFlowById(id);
		
		 return new TaskFlowProcess(taskFlow).runWorkFlow();




	}
	
	
	
	

	public List<TaskFlow> getTopTaskFlow(Account account)
	{
		List<TaskFlow> result=taskDao.getTaskFlowList( account);
		
		return result;
	}
	
	
	
	
	/**
	 * 
	 * @param type
	 * @param id
	 * @return
	 */
	public Log getLogInfo(String type,Long id)
	{
		Log log=new Log();
		
		if (type.equalsIgnoreCase("taskFlowLog")) {
			
			TaskFlow taskFlow=taskDao.getTaskFlowById(id);
			
			TaskFlowLog taskFlowLog=logDao.getTaskFlowLog(taskFlow);
			
			if(taskFlowLog!=null)
			{
				log.setLogName(taskFlowLog.getLogName());
				log.setLogDetail(taskFlowLog.getStringMessages());
				log.setDateTime(taskFlowLog.getDateTime());
			}
			
		}else if(type.equalsIgnoreCase("taskLog"))
		{
			Task task=taskDao.getTaskById(id);
			
			TaskLog taskLog=logDao.getTaskLogByTask(task);
			
			if(taskLog!=null)
			{
				log.setLogName(taskLog.getLogName());
				log.setLogDetail(taskLog.getStringMessages());
				log.setDateTime(taskLog.getDateTime());
			}
			
		}
		
		
		return log;
		
	}

	public void saveTaskFlow(TaskFlow taskFlow) {
		
		taskDao.saveTaskFlow(taskFlow);
	}

	public List<IDataAdaptor> getDataAdaptor(FormulaRestEntity formulaRestEntity) throws IOException {
		
		Task task=taskDao.getTaskById(formulaRestEntity.getTaskId());
		
		DataAdaptorProcess dataAdaptorProcess=new DataAdaptorProcess(task);
		
		List<IDataAdaptor> dataAdaptors=dataAdaptorProcess.getDataAdaptors();
		
		Operation op=projectBiz.getOperationByKey(task.getOperation());
		
		DataTemplate template= op.getDataAdaptorData();
		
		Formula formula= dataAdaptorBiz.getFormula(template);
		
		List<IDataAdaptor> returnAdaptors=new ArrayList<IDataAdaptor>();
		for (IDataAdaptor dataAdaptor : dataAdaptors) {
			
			IDataAdaptor result=dataAdaptor;
			
			if(formulaRestEntity.isFilter())
			{
				DataFilter datafilter = new DataFilter(result, formula);
				result=datafilter.Process();
			}
			
			
			if(formulaRestEntity.isFormula())
			{
				FormulaProcess formulaProcess = new FormulaProcess(result, formula);
				result=formulaProcess.Process();
			}
			
			returnAdaptors.add(result);
		}
		
		return returnAdaptors;
		
		
	}
	
	
	
	

}
